package Utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

/**
 * DateTimeUtils工具类
 *
 * @author d11yu
 */
public final class DateTimeUtils {
    /**
     * 将Calendar转换为ZonedDateTime。
     *
     * @param calendar Calendar对象
     * @return 返回ZonedDateTime对象
     */
    public static ZonedDateTime calendarToZonedDateTime(Calendar calendar) {
        return calendar.toInstant().atZone(calendar.getTimeZone().toZoneId());
    }

    /**
     * 将ZonedDateTime转换为Calendar。
     *
     * @param zdt ZonedDateTime对象
     * @return 返回Calendar对象
     */
    public static Calendar zonedDateTimeToCalendar(ZonedDateTime zdt) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.setTimeZone(TimeZone.getTimeZone(zdt.getZone().getId()));
        calendar.setTimeInMillis(zdt.toEpochSecond() * 1000);
        return calendar;
    }

    /**
     * 将长整型时间（常用于数据库）转换为字符串时间。
     *
     * @param epochMilli 长整型时间
     * @param locale     Locale
     * @param zoneId     ZoneID
     * @return 返回字符串时间
     */
    public static String timestampToString(long epochMilli, Locale locale, ZoneId zoneId) {
        Instant ins = Instant.ofEpochMilli(epochMilli);
        DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.SHORT);
        return formatter.withLocale(locale).format(ZonedDateTime.ofInstant(ins, zoneId));
    }

    /**
     * 将长整型时间（常用于数据库）转换为字符串时间。
     *
     * @param epochMilli 长整型时间
     * @param locale     Locale
     * @param zoneId     ZoneID
     * @return 返回字符串时间
     */
    public static String timestampToString(long epochMilli, Locale locale, String zoneId) {
        Instant ins = Instant.ofEpochMilli(epochMilli);
        DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.SHORT);
        return formatter.withLocale(locale).format(ZonedDateTime.ofInstant(ins, ZoneId.of(zoneId)));
    }

    /**
     * 将长整型时间（常用于数据库）转换为字符串时间。
     *
     * @param epochMilli 长整型时间
     * @param formatter  DateTimeFormatter对象
     * @param zoneId     ZoneID
     * @return 返回字符串时间
     */
    public static String timestampToString(long epochMilli, DateTimeFormatter formatter, ZoneId zoneId) {
        Instant ins = Instant.ofEpochMilli(epochMilli);
        return formatter.format(ZonedDateTime.ofInstant(ins, zoneId));
    }

    /**
     * 将长整型时间（常用于数据库）转换为字符串时间。
     *
     * @param epochMilli 长整型时间
     * @param formatter  DateTimeFormatter对象
     * @param zoneId     ZoneID
     * @return 返回字符串时间
     */
    public static String timestampToString(long epochMilli, DateTimeFormatter formatter, String zoneId) {
        Instant ins = Instant.ofEpochMilli(epochMilli);
        return formatter.format(ZonedDateTime.ofInstant(ins, ZoneId.of(zoneId)));
    }

    /**
     * 获取当前日期
     *
     * @return
     */
    public static LocalDate getNowDate() {
        return LocalDate.now();
    }

    /**
     * 获取当前时间
     *
     * @return
     */
    public static LocalTime getNowTime() {
        return LocalTime.now();
    }

    /**
     * 获取当前日期、时间
     *
     * @return
     */
    public static LocalDateTime getNowDateTime() {
        return LocalDateTime.now();
    }

    /**
     * 获取指定时间，使用SimpleDateFormat。（不建议在循环内使用）
     *
     * @param dateOrTime 指定的时间，例："2022-3-31"。
     * @param format     指定的时间格式，例"yyyy-MM-dd"或"yyyy-MM-dd HH:mm:ss"。
     * @return
     * @throws ParseException
     */
    public static Date getDateOrTimeSdfUtil(String dateOrTime, String format) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.parse(dateOrTime);
    }

    /**
     * 获取指定时间（java.sql.date），使用SimpleDateFormat。（不建议在循环内使用）
     *
     * @param dateOrTime 指定的时间，例："2022-3-31"。
     * @param sdf        SimpleDateFormat，指定的时间，例："2022-3-31"。
     * @return
     * @throws ParseException
     */
    public static java.sql.Date getDateOrTimeSdfSql(String dateOrTime, SimpleDateFormat sdf) throws ParseException {
        return utilDate2SqlDate(getDateOrTimeSdfUtil(dateOrTime, sdf));
    }

    /**
     * 获取指定时间（java.sql.date），使用SimpleDateFormat。（不建议在循环内使用）
     *
     * @param dateOrTime 指定的时间，例："2022-3-31"。
     * @param format     指定的时间格式，例"yyyy-MM-dd"或"yyyy-MM-dd HH:mm:ss"。
     * @return
     * @throws ParseException
     */
    public static java.sql.Date getDateOrTimeSdfSql(String dateOrTime, String format) throws ParseException {
        return utilDate2SqlDate(getDateOrTimeSdfUtil(dateOrTime, format));
    }

    /**
     * 获取指定时间，使用SimpleDateFormat。
     *
     * @param dateOrTime 指定的时间，例："2022-3-31"。
     * @param sdf        SimpleDateFormat，指定的时间格式，例"yyyy-MM-dd"或"yyyy-MM-dd HH:mm:ss"。
     * @return
     * @throws ParseException
     */
    public static Date getDateOrTimeSdfUtil(String dateOrTime, SimpleDateFormat sdf) throws ParseException {
        return sdf.parse(dateOrTime);
    }

    /**
     * 获取指定时间，使用SimpleDateFormat，以字符串的形式返回。
     *
     * @param format 指定的时间格式，例"yyyy-MM-dd"或"yyyy-MM-dd HH:mm:ss"。
     * @return
     * @throws ParseException
     */
    public static String getNowSdf(String format) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date date = new Date();
        return sdf.format(date);
    }

    /**
     * 将日期转换为指定格式的字符串。
     *
     * @param date   带转换的日期
     * @param format 指定的时间格式，例"yyyy-MM-dd"或"yyyy-MM-dd HH:mm:ss"。
     * @return
     */
    public static String dateToString(Date date, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(date);
    }

    /**
     * 将日期时间转换为指定格式的字符串。
     *
     * @param dateTime   带转换的日期时间
     * @param format 指定的时间格式，例"yyyy-MM-dd"或"yyyy-MM-dd HH:mm:ss"。
     * @return
     */
    public static String dateTimeToString(LocalDateTime dateTime, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(dateTime);
    }

    /**
     * 获取当前时间
     *
     * @return
     */
    public static Date getNow() {
        return new Date();
    }

    /**
     * 将utilDate转化为SqlDate。
     *
     * @param date
     * @return
     */
    public static java.sql.Date utilDate2SqlDate(Date date) {
        return new java.sql.Date(date.getTime());
    }

    /**
     * 将java.sql.Date转化为java.util.Date
     *
     * @param date
     * @return
     */
    public static Date sqlDate2UtilDate(java.sql.Date date) {
        return new Date(date.getTime());
    }

    /**
     * 将util Date转为LocalDateTime
     *
     * @param date
     * @return
     */
    public static LocalDateTime utilDate2LocalDateTime(Date date) {
        return utilDate2LocalDateTime(date, ZoneId.systemDefault());
    }

    /**
     * 将util Date转为LocalDateTime
     *
     * @param date
     * @param zoneId 默认为系统时区id
     * @return
     */
    public static LocalDateTime utilDate2LocalDateTime(Date date, ZoneId zoneId) {
        Instant instant = date.toInstant();
        return instant.atZone(zoneId).toLocalDateTime();
    }

    /**
     * 将LocalDateTime转换为util Date
     *
     * @param ldt
     * @return
     */
    public static Date localDateTime2UtilDate(LocalDateTime ldt) {
        return localDateTime2UtilDate(ldt, ZoneId.systemDefault());
    }

    /**
     * 将LocalDateTime转换为util Date
     *
     * @param ldt
     * @param zoneId 默认为系统时区id
     * @return
     */
    public static Date localDateTime2UtilDate(LocalDateTime ldt, ZoneId zoneId) {
        ZonedDateTime zdt = ldt.atZone(zoneId);
        return Date.from(zdt.toInstant());
    }
}
